package com.xiangyun.versionhelper;

import com.alibaba.druid.pool.DruidPooledPreparedStatement;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.plugin.*;
import org.springframework.util.StringUtils;
import java.sql.*;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

/**
 * Created by wangxiangyun on 2019/1/23.
 */
@Intercepts(@Signature(type = StatementHandler.class, method = "update", args = Statement.class))
@Slf4j
public class VersionHelper implements Interceptor {
    private String versionField;
    private  final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd  HH:mm:ss");

    public static void checkVersion(java.util.Date oldUpdateTime) {
        VersionContext.setLocalDate(oldUpdateTime);
    }

    public static java.util.Date getVersionChecked() {
        return VersionContext.getLocalDate();
    }


    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        //没有设置标志直接放过不拦截
        if (VersionHelper.getVersionChecked() == null) {
            return invocation.proceed();
        }
        PreparedStatement orginPreparedStatement = (PreparedStatement) invocation.getArgs()[0];
        DruidPooledPreparedStatement druidPooledPreparedStatement = (DruidPooledPreparedStatement) orginPreparedStatement;
        Statement statement = druidPooledPreparedStatement.getStatement();
        String updateSql = ((com.mysql.jdbc.PreparedStatement) statement)
                .asSql()
                .toLowerCase()
                .replaceAll("\\s+", " ");
        String table = updateSql.split(" ")[1];
        String where =updateSql.substring(updateSql.indexOf("where"),updateSql.length());
        String versionSql = "select " + this.getVersionField() + " from " + table +" "+ where;
        Connection conn = statement.getConnection();
        PreparedStatement preparedStatement = null;
        try {
            preparedStatement = conn.prepareStatement(versionSql);
            ResultSet resultSet = preparedStatement.executeQuery();
            Timestamp updateTime = this.populate(resultSet);
            String sqlUpdateTimeStr = simpleDateFormat.format(VersionContext.getLocalDate());
            String updateTimeStr = simpleDateFormat.format(updateTime);
            if (!sqlUpdateTimeStr.equals(updateTimeStr)) {
                log.warn("当前版本已经被修改过！请刷新页面 表名称：{} 过滤参数：{}", table, where);
                throw new VersionPersistenceException("数据已被更改，请重新查询后再编辑！");
            }
        } finally {
            if (VersionHelper.getVersionChecked() != null) {
                VersionContext.clear();
            }
            if (preparedStatement != null) {
                preparedStatement.close();
            }
        }
        return invocation.proceed();
    }

    @Override
    public Object plugin(Object o) {
        return Plugin.wrap(o, this);
    }

    @Override
    public void setProperties(Properties properties) {
        String versionField = properties.getProperty("versionField");
        if (StringUtils.isEmpty(versionField)) {
            versionField = "update_time";
        }
        this.setVersionField(versionField);
    }

    public String getVersionField() {
        return versionField;
    }

    public void setVersionField(String versionField) {
        this.versionField = versionField;
    }

    public Timestamp populate(ResultSet rs)
            throws SQLException, InstantiationException, IllegalAccessException {
        //结果集的元素对象
        ResultSetMetaData rsmd = rs.getMetaData();
        //获取结果集的元素个数
        int colCount = rsmd.getColumnCount();
        //返回结果的列表集合
        List<Timestamp> list = new ArrayList();
        //业务对象的属性数组
        while (rs.next()) {//对每一条记录进行操作
            //将每一个字段取出进行赋值
            for (int i = 1; i <= colCount; i++) {
                Timestamp date = rs.getTimestamp(i);
                list.add(date);
            }

        }
        return list.get(0);
    }
}
